package metronome;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;

import javax.sound.sampled.LineUnavailableException;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.SliderUI;

import java.awt.Font;
import java.awt.Color;
import java.io.IOException;
/**
 * User Interface of application.
 * @author Suwijak Suppapit 5510546204
 * @version 5/1/2013
 */
public class MetronomeUI extends JFrame {

	Metronome metronome;
	Tuner tuner;
	private Timer timer;

	JPanel metronomePanel;
	JPanel radioPanel;
	JPanel choosePane;
	JPanel tunerPanel;
	JPanel showBPM;
	JPanel spacePane;

	JLabel metronomeLabel;
	JLabel tunerJLabel;
	JLabel warning;
	JLabel bpmNum;
	JLabel num;
	
	NoteAction wholeAction;
	NoteAction halfAction;
	NoteAction quarterAction;
	NoteAction eigthAction;
	NoteAction sixteenthAction;

	ButtonGroup radioGroup;

	JRadioButton wholeNote;// /4
	JRadioButton halfNote;// /2
	JRadioButton quarterNote;// x1
	JRadioButton eigthNote;// x2
	JRadioButton sixteenthNote;// x4

	JButton playButton;
	JButton stopButton;
	JButton wireOne;
	JButton wireTwo;
	JButton wireThree;
	JButton wireFour;
	JButton wireFive;
	JButton wireSix;

	JSlider bpmSlide;

	Color color = new Color(102, 204, 153);

	/**
	 * Initailize User Interface
	 * @param metronome metronome
	 */
	public MetronomeUI(Metronome metronome) {
		setBackground(color);
		this.metronome = metronome;
		tuner = new Tuner();
		initComponent();

	}

	/**
	 * Edit and set actions for components.
	 */
	public void initComponent() {
		int min = 60;
		int max = 180;
		int value = (int) metronome.getBpm();

		wholeAction = new NoteAction(0.25);
		halfAction = new NoteAction(0.5);
		quarterAction = new NoteAction(1);
		eigthAction = new NoteAction(2);
		sixteenthAction = new NoteAction(4);
		
		metronomePanel = new JPanel();
		radioPanel = new JPanel();
		choosePane = new JPanel();
		tunerPanel = new JPanel();
		showBPM = new JPanel();
		spacePane = new JPanel();

		metronomeLabel = new JLabel("Metronome");
		metronomeLabel.setFont(new Font("Harrington", Font.BOLD, 18));
		warning = new JLabel(
				"Please press \"stop\" before choosing new frequency");
		tunerJLabel = new JLabel("Tuner");
		tunerJLabel.setFont(new Font("Harrington", Font.BOLD, 18));
		bpmNum = new JLabel("BPM: ");
		num = new JLabel();

		radioGroup = new ButtonGroup();

		wholeNote = new JRadioButton("Whole Note");
		wholeNote.setBackground(color);
		halfNote = new JRadioButton("Half Note");
		halfNote.setBackground(color);
		quarterNote = new JRadioButton("Quarter Note");
		quarterNote.setBackground(color);
		quarterNote.setSelected(true);
		eigthNote = new JRadioButton("Eigth Note");
		eigthNote.setBackground(color);
		sixteenthNote = new JRadioButton("Sixteenth Note");
		sixteenthNote.setBackground(color);

		playButton = new JButton("Play");
		stopButton = new JButton("Stop");
		wireOne = new JButton("E (6th)");
		wireTwo = new JButton("A (5th)");
		wireThree = new JButton("D (4th)");
		wireFour = new JButton("G (3th)");
		wireFive = new JButton("B (2th)");
		wireSix = new JButton("E (1th)");

		bpmSlide = new JSlider(min, max, value);

		bpmSlide.setMajorTickSpacing(10);
		bpmSlide.setMinorTickSpacing(10);
		bpmSlide.setPaintTicks(true);
		bpmSlide.setPaintLabels(true);
		bpmSlide.setPreferredSize(new Dimension(320, 120));
		bpmSlide.setBackground(color);

		radioGroup.add(wholeNote);
		radioGroup.add(halfNote);
		radioGroup.add(quarterNote);
		radioGroup.add(eigthNote);
		radioGroup.add(sixteenthNote);

		playButton.setPreferredSize(new Dimension(60, 60));
		stopButton.setPreferredSize(new Dimension(60, 60));

		radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS));
		radioPanel.add(wholeNote);
		radioPanel.add(halfNote);
		radioPanel.add(quarterNote);
		radioPanel.add(eigthNote);
		radioPanel.add(sixteenthNote);
		radioPanel.setBackground(color);

		showBPM.setLayout(new BoxLayout(showBPM, BoxLayout.X_AXIS));
		showBPM.add(bpmNum);
		showBPM.add(Box.createRigidArea(new Dimension(10, 0)));
		showBPM.add(num);
		showBPM.setBackground(color);

		choosePane.setLayout(new BoxLayout(choosePane, BoxLayout.X_AXIS));
		choosePane.add(radioPanel);
		choosePane.add(Box.createRigidArea(new Dimension(25, 0)));
		choosePane.add(playButton);
		choosePane.add(Box.createRigidArea(new Dimension(15, 0)));
		choosePane.add(stopButton);
		choosePane.setBackground(color);

		metronomePanel
				.setLayout(new BoxLayout(metronomePanel, BoxLayout.Y_AXIS));
		metronomePanel.setPreferredSize(new Dimension(600, 300));
		metronomePanel.add(metronomeLabel);
		metronomePanel.add(Box.createRigidArea(new Dimension(0, 15)));
		metronomePanel.add(choosePane);
		metronomePanel.add(Box.createRigidArea(new Dimension(0, 15)));
		metronomePanel.add(bpmSlide);
		metronomePanel.add(Box.createRigidArea(new Dimension(0, 15)));
		metronomePanel.add(warning);
		metronomePanel.add(Box.createRigidArea(new Dimension(0, 25)));
		metronomePanel.add(showBPM);
		metronomePanel.add(Box.createRigidArea(new Dimension(0, 20)));
		metronomePanel.setBackground(color);

		spacePane.setPreferredSize(new Dimension(40, 30));
		spacePane.setBackground(color);

		tunerPanel.setLayout(new BoxLayout(tunerPanel, BoxLayout.Y_AXIS));
		tunerPanel.add(tunerJLabel);
		tunerPanel.add(Box.createRigidArea(new Dimension(0, 20)));
		tunerPanel.add(wireOne);
		tunerPanel.add(Box.createRigidArea(new Dimension(0, 10)));
		tunerPanel.add(wireTwo);
		tunerPanel.add(Box.createRigidArea(new Dimension(0, 10)));
		tunerPanel.add(wireThree);
		tunerPanel.add(Box.createRigidArea(new Dimension(0, 10)));
		tunerPanel.add(wireFour);
		tunerPanel.add(Box.createRigidArea(new Dimension(0, 10)));
		tunerPanel.add(wireFive);
		tunerPanel.add(Box.createRigidArea(new Dimension(0, 10)));
		tunerPanel.add(wireSix);
		tunerPanel.setBackground(color);

		getContentPane().add(metronomePanel, BorderLayout.WEST);
		getContentPane().add(spacePane, BorderLayout.CENTER);
		getContentPane().add(tunerPanel, BorderLayout.EAST);

		wholeNote.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				wholeAction.actionPerformed(arg0);
			}
		});
		
		halfNote.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				halfAction.actionPerformed(arg0);
			}
		});
		
		quarterNote.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				quarterAction.actionPerformed(arg0);
			}
		});
		
		eigthNote.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				eigthAction.actionPerformed(arg0);
			}
		});
		
		sixteenthNote.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				sixteenthAction.actionPerformed(arg0);
			}
		});

		playButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				timer = new Timer();
				MetronomeTask metronomeTask = new MetronomeTask(metronome);
				metronome.getState().performPlay();
				timer.scheduleAtFixedRate(metronomeTask, 0,
						60000 / (int) metronome.getBpm());
				stopButton.setEnabled(true);
				playButton.setEnabled(false);
			}
		});
		
		stopButton.setEnabled(false);
		stopButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				
				
				metronome.getState().performStop();
				// metronome.setState(metronome.stopState);
				timer.cancel();
				stopButton.setEnabled(false);
				playButton.setEnabled(true);
			}
		});

		bpmSlide.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent arg0) {
				quarterNote.setSelected(true);
				JSlider source = (JSlider) arg0.getSource();
				int newBpm = source.getValue();
				metronome.setBpm(newBpm);
				num.setText(metronome.getBpm() + "");
				
			}
		});

		num.setText(metronome.getBpm() + "");

		wireOne.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				tuner.playE6();
			}
		});

		wireTwo.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				tuner.playA5();
			}
		});

		wireThree.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				tuner.playD4();
			}
		});

		wireFour.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				tuner.playG3();
			}
		});

		wireFive.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				tuner.playB2();
			}
		});

		wireSix.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				tuner.playE1();
			}
		});

		this.pack();
		this.setResizable(false);
		this.setVisible(true);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

	}

	class NoteAction extends AbstractAction {
		private double note;

		public NoteAction(double note) {
			this.note = note;
		}

		@Override
		public void actionPerformed(ActionEvent arg0) {
			// TODO Auto-generated method stub
			metronome.setBpm(bpmSlide.getValue() * note);
		}

	}
}
